/**
 * @ignore
 * only one droppable instance for multiple droppable nodes
 * @author yiminghe@gmail.com
 */

var $ = require('node'),
    DDM = require('./ddm'),
    Droppable = require('./droppable');
var util = require('util');
function dragStart() {
    var self = this,
        container = self.get('container'),
        allNodes = [],
        selector = self.get('selector');
    container.all(selector).each(function (n) {
        // 2012-05-18: 缓存高宽，提高性能
        DDM.cacheWH(n);
        allNodes.push(n);
    });
    self.__allNodes = allNodes;
}

/**
 * @class KISSY.DD.DroppableDelegate
 * @extend KISSY.DD.Droppable
 * Make multiple nodes droppable under a container using only one droppable instance.
 */
var DroppableDelegate = Droppable.extend({

    initializer: function () {
        // 提高性能，拖放开始时缓存代理节点
        DDM.on('dragstart', dragStart, this);
    },

    /**
     * get droppable node by delegation
     * @protected
     */
    getNodeFromTarget: function (ev, dragNode, proxyNode) {
        var pointer = {
                left: ev.pageX,
                top: ev.pageY
            },
            self = this,
            allNodes = self.__allNodes,
            ret = 0,
            vArea = Number.MAX_VALUE;

        if (allNodes) {
            util.each(allNodes, function (n) {
                var domNode = n[0];
                // 排除当前拖放的元素以及代理节点
                if (domNode === proxyNode || domNode === dragNode) {
                    return;
                }
                var r = DDM.region(n);
                if (DDM.inRegion(r, pointer)) {
                    // 找到面积最小的那个
                    var a = DDM.area(r);
                    if (a < vArea) {
                        vArea = a;
                        ret = n;
                    }
                }
            });
        }

        if (ret) {
            self.setInternal('lastNode', self.get('node'));
            self.setInternal('node', ret);
        }

        return ret;
    },

    _handleOut: function () {
        var self = this;
        self.callSuper();
        self.setInternal('node', 0);
        self.setInternal('lastNode', 0);
    },

    _handleOver: function (ev) {
        var self = this,
            node = self.get('node'),
            superOut = DroppableDelegate.superclass._handleOut,
            superOver = self.callSuper,
            superEnter = DroppableDelegate.superclass._handleEnter,
            lastNode = self.get('lastNode');

        if (lastNode[0] !== node[0]) {

            // 同一个 drop 对象内委托的两个可 drop 节点相邻，先通知上次的离开
            self.setInternal('node', lastNode);
            superOut.apply(self, arguments);

            // 再通知这次的进入
            self.setInternal('node', node);
            superEnter.call(self, ev);
        } else {
            superOver.call(self, ev);
        }
    },

    _end: function (e) {
        var self = this;
        self.callSuper(e);
        self.setInternal('node', 0);
    }
}, {
    ATTRS: {

        /**
         * last droppable target node.
         * @property lastNode
         * @private
         */
        /**
         * @ignore
         */
        lastNode: {
        },

        /**
         * a selector query to get the children of container to make droppable elements from.
         * usually as for tag.cls.
         * @cfg {String} selector
         */
        /**
         * @ignore
         */
        selector: {
        },

        /**
         * a selector query to get the container to listen for mousedown events on.
         * All 'draggable selector' should be a child of this container
         * @cfg {String|HTMLElement} container
         */
        /**
         * @ignore
         */
        container: {
            setter: function (v) {
                return $(v);
            }
        }
    }
});

module.exports = DroppableDelegate;